#ifndef PUBLIC_WJ_DEV_H_INCLUDED
#define PUBLIC_WJ_DEV_H_INCLUDED
#include "WJ.h"

typedef enum {
    WJ_FALSE = 0,
    WJ_TRUE = 1
} WJ_Boolean;

typedef enum {
	WUJI_FUNCTION_DEFINITION = 1,	/* 解释器中定义过的函数 */
	NATIVE_FUNCTION_DEFINITION,
	FUNCTION_DEFINITION_TYPE_COUNT_PLUS_1
} FunctionDefinitionType;

typedef struct WJ_Object_tag WJ_Object;
typedef struct WJ_Array_tag WJ_Array;
typedef struct WJ_String_tag WJ_String;
typedef struct WJ_Assoc_tag WJ_Assoc;
typedef struct WJ_ParameterList_tag ParameterList;
typedef struct WJ_Block_tag	Block;
typedef struct WJ_FunctionDefinition_tag FunctionDefinition;
typedef struct WJ_LocalEnvironment_tag WJ_LocalEnvironment;

typedef enum {
    WJ_BOOLEAN_VALUE = 1,
    WJ_INT_VALUE,
    WJ_DOUBLE_VALUE,
    WJ_STRING_VALUE,
    WJ_NATIVE_POINTER_VALUE,
    WJ_NULL_VALUE,
    WJ_ARRAY_VALUE,
	WJ_ASSOC_VALUE,
	WJ_CLOSURE_VALUE,
	WJ_FAKE_METHOD_VALUE,
	WJ_SCOPE_CHAIN_VALUE
} WJ_ValueType;

typedef struct {
	FunctionDefinition	*function;
	WJ_Object			*environment;
} WJ_Closure;

typedef struct {
	char		*method_name;
	WJ_Object	*object;
} WJ_FakeMethod;

typedef struct {
    WJ_ValueType			type;
    union {
        WJ_Boolean			boolean_value;
        int					int_value;
        double				double_value;
        WJ_Object			*object;
		WJ_Closure			closure;
		WJ_FakeMethod		fake_method;
    } u;
} WJ_Value;

typedef enum {
	INT_MESSAGE_ARGUMENT = 1,
	DOUBLE_MESSAGE_ARGUMENT,
	STRING_MESSAGE_ARGUMENT,
	CHARACTER_MESSAGE_ARGUMENT,
	POINTER_MESSAGE_ARGUMENT,
	MESSAGE_ARGUMENT_END
} MessageArgumentType;

typedef struct {
	char *format;
	char *class_name;
} ErrorMessageFormat;

typedef struct {
	ErrorMessageFormat *message_format;
} WJ_NativeLibInfo;

typedef void WJ_NativePointerFinalizeProc(WJ_Interpreter *inter, WJ_Object *obj);

typedef struct {
	char		*name;
	WJ_NativePointerFinalizeProc	*finalizer;
} WJ_NativePointerInfo;

typedef WJ_Value WJ_NativeFunctionProc(WJ_Interpreter *interpreter,
										WJ_LocalEnvironment *env,
                                        int arg_count, WJ_Value *args);

struct WJ_FunctionDefinition_tag {
    char					*name;	/* 函数名 */
    FunctionDefinitionType	type;	/* 函数类型 */
	WJ_Boolean				is_closure;
    union {
        struct {
            ParameterList       *parameter;	/* 参数的定义 */
            Block               *block;		/* 函数的主体 */
        } wuji_f;							/* 解释器定义的函数 */
        struct {
            WJ_NativeFunctionProc      *proc;	
		} native_f;							/* 内置函数使用 */
    } u;
    struct WJ_FunctionDefinition_tag       *next;	/* 下一个函数的指针，链表用 */
};


/* interface.c */
FunctionDefinition *
WJ_add_native_function(WJ_Interpreter *interpreter, char *name, WJ_NativeFunctionProc *proc);


/* nativeif.c */
char *WJ_object_get_string(WJ_Object *obj);
void *
WJ_object_get_native_pointer(WJ_Object *obj);
void
WJ_object_set_native_pointer(WJ_Object *obj, void *p);
WJ_Value *
WJ_array_get(WJ_Interpreter *inter, WJ_LocalEnvironment *env,
              WJ_Object *obj, int index);
void
WJ_array_set(WJ_Interpreter *inter, WJ_LocalEnvironment *env,
              WJ_Object *obj, int index, WJ_Value *value);
WJ_Value
WJ_create_closure(WJ_LocalEnvironment *env, FunctionDefinition *fd);
void
WJ_set_function_definition(char *name, WJ_NativeFunctionProc *proc,
                            FunctionDefinition *fd);

/* eval.c */
void 
WJ_push_value(WJ_Interpreter *inter, WJ_Value *value);
WJ_Value 
WJ_pop_value(WJ_Interpreter *inter, int index);
WJ_Value *
WJ_peek_stack(WJ_Interpreter *inter, int index);
void
WJ_shrink_stack(WJ_Interpreter *inter, int shrink_size);
WJ_Value
WJ_call_function(WJ_Interpreter *inter, WJ_LocalEnvironment *env,
				int line_number, WJ_Value *func,
				int arg_count, WJ_Value *args);
WJ_Value
WJ_call_function_by_name(WJ_Interpreter *inter, WJ_LocalEnvironment *env,
						int line_number, char *func_name, int arg_count, WJ_Value *args);
WJ_Value
WJ_call_method(WJ_Interpreter *inter, WJ_LocalEnvironment *env,
			int line_number, WJ_Object *obj, char *method_name,
			int arg_count, WJ_Value *args);



/* heap.c */
WJ_Object *
WJ_create_wuji_string(WJ_Interpreter *inter, WJ_LocalEnvironment *env,
                          char *str);
WJ_Object *
WJ_create_array(WJ_Interpreter *inter, WJ_LocalEnvironment *env,
                 int size);
WJ_Object *
WJ_create_assoc(WJ_Interpreter *inter, WJ_LocalEnvironment *env);
void
WJ_array_resize(WJ_Interpreter *inter, WJ_Object *obj, int new_size);
void
WJ_array_add(WJ_Interpreter *inter, WJ_Object *obj, WJ_Value *v);
void
WJ_array_insert(WJ_Interpreter *inter, WJ_LocalEnvironment *env,
				WJ_Object *obj, int pos,
				WJ_Value *new_value, int line_number);
void 
WJ_array_remove(WJ_Interpreter *inter, WJ_LocalEnvironment *env,
				WJ_Object *obj, int pos, int line_number);
WJ_Object *
WJ_literal_to_wj_string(WJ_Interpreter *inter, WJ_LocalEnvironment *env, char *str);
WJ_Object *
WJ_string_substr(WJ_Interpreter *inter, WJ_LocalEnvironment *env,
			WJ_Object *str, int from, int len, int line_number);
WJ_Value *
WJ_add_assoc_member(WJ_Interpreter *inter, WJ_Object *assoc,
					char *name, WJ_Value *value, WJ_Boolean is_final);

void 
WJ_add_assoc_member2(WJ_Interpreter *inter, WJ_Object *assoc,
					char *name, WJ_Value *value);
WJ_Value *
WJ_search_assoc_member(WJ_Object *assoc, char *member_name);
WJ_Value *
WJ_search_assoc_member_w(WJ_Object *assoc, char *member_name,
						WJ_Boolean *is_final);
WJ_Object *
WJ_create_native_pointer(WJ_Interpreter *inter, WJ_LocalEnvironment *env,
						void *pointer, WJ_NativePointerInfo *info);
WJ_Boolean
WJ_check_native_pointer_type(WJ_Object *native_pointer,
							WJ_NativePointerInfo *info);
WJ_NativePointerInfo *
WJ_get_native_pointer_type(WJ_Object *native_pointer);
WJ_Object *WJ_create_exception(WJ_Interpreter *inter, WJ_LocalEnvironment *env, WJ_Object *message, int line_number);


/* util.c */
FunctionDefinition *wj_search_function(char *name);
WJ_Value *
WJ_search_local_variable(WJ_LocalEnvironment *env, char *identifier);
WJ_Value *
WJ_search_local_variable_w(WJ_LocalEnvironment *env, char *identifier, WJ_Boolean *is_final);
WJ_Value *
WJ_search_global_variable(WJ_Interpreter *inter, char *identifier);
WJ_Value *
WJ_search_global_variable_w(WJ_Interpreter *inter, char *identifier,
							WJ_Boolean *is_final);
WJ_Value *
WJ_add_local_variable(WJ_Interpreter *inter, WJ_LocalEnvironment *env,
					char *identifier, WJ_Value *value, WJ_Boolean is_final);
WJ_Value *
WJ_add_global_variable(WJ_Interpreter *inter, char *identifier,
					WJ_Value *value, WJ_Boolean is_final);
char *
WJ_value_to_string(WJ_Value *value);
char *
WJ_get_type_name(WJ_ValueType type);
char *
WJ_get_object_type_name(WJ_Object *obj);



/* nativeif.c */
char *
WJ_object_get_string(WJ_Object *obj);
void *
WJ_object_get_native_pointer(WJ_Object *obj);
void
WJ_object_set_native_pointer(WJ_Object *obj, void *p);
WJ_Value *
WJ_array_get(WJ_Interpreter *inter, WJ_LocalEnvironment *env,
              WJ_Object *obj, int index);
void
WJ_array_set(WJ_Interpreter *inter, WJ_LocalEnvironment *env,
              WJ_Object *obj, int index, WJ_Value *value);
WJ_Value
WJ_create_closure(WJ_LocalEnvironment *env, FunctionDefinition *fd);
void
WJ_set_function_definition(char *name, WJ_NativeFunctionProc *proc,
                            FunctionDefinition *fd);




#endif /* PUBLIC_WJ_DEV_H_INCLUDED */
